/////////////////////////////////////
//	dzh 2018-03-22 对sqlite进行封装 //
/////////////////////////////////////
// 简单使用
/*
DBSQLite *db = new DBSQLite();
db->connect("info.db");

DBSQLite::Result res;
db->query("select * from student", res);

if (db->isError()){
	printf("%s\n", db->getLastErrorMessage());
}

Student sdt;
for(int i=0;i<res.rows();i++){
sdt.id = res[i][0];
}
*/

#pragma once

#include "stdlib.h"
#include "string.h"
#include "sqlite3.h"
#pragma comment(lib,"sqlite.lib")

class DBSQLite
{
public:
	class Result
	{
	public:
		class Row
		{
		public:
			Row(){}
			~Row(){}

			char* operator[](int i)
			{
				return m_res->m_vals[m_cur_row][i];
			}

		private:
			Result *m_res;
			int m_cur_row;

			friend class Result;
		};

		Result(){
			m_ins_row.m_res = this;
		}
		~Result(){}

		int rows(){ return m_rows; }
		int cols(){ return m_cols; }

		Row& operator[](int i)
		{
			m_ins_row.m_cur_row = i;
			return m_ins_row;
		}

	private:
		int m_rows = 0;
		int m_cols = 0;

		Row m_ins_row;

		char** m_keys = NULL;
		char*** m_vals = NULL;


		void addRow(char** vals){
			char*** tmp;

			// 申请空间
			if ((m_rows % 100) == 0){
				tmp = m_vals;
				m_vals = (char***)malloc((100 * (m_rows / 100) + 100)*sizeof(char*));
				if (m_rows != 0){
					memcpy(m_vals, tmp, 100 * ((m_rows / 100)*sizeof(char*)));
					free(tmp);
				}
			}

			// 赋值
			m_vals[m_rows] = (char**)malloc(m_cols*sizeof(char*));
			for (int i = 0; i < m_cols; i++){
				m_vals[m_rows][i] = (char*)malloc(strlen(vals[i]) + 1);
				strcpy(m_vals[m_rows][i], vals[i]);
			}

			// 行号自加
			m_rows++;
		}
		void setColsKey(int cols, char** keys)
		{
			m_cols = cols;
			m_keys = (char**)malloc(cols*sizeof(char*));
			for (int i = 0; i < cols; i++){
				m_keys[i] = (char*)malloc(strlen(keys[i]) + 1);
				strcpy(m_keys[i], keys[i]);
			}
		}

		friend class DBSQLite;
	};

	DBSQLite(){}
	~DBSQLite(){
		if (m_error_message != NULL){
			free(m_error_message);
		}

		while (SQLITE_BUSY == sqlite3_close(m_db));
	}

	bool connect(const char* filename){
		m_error_code = sqlite3_open(filename, &m_db);

		// 打开失败
		if (m_error_code){
			const char *msg = sqlite3_errmsg(m_db);

			saveMessage(msg);
			return false;
		}

		return true;
	}

	bool exec(const char* sql)
	{
		char *msg;
		m_error_code = sqlite3_exec(m_db, sql, NULL, 0, &msg);
		if (m_error_code != SQLITE_OK){
			saveMessage(msg);
			sqlite3_free(msg);
			return false;
		}

		return true;
	}

	bool squry(const char* sql, Result &res)
	{
		char *msg;
		m_error_code = sqlite3_exec(m_db, sql, callback, &res, &msg);
		if (m_error_code != SQLITE_OK){
			saveMessage(msg);
			sqlite3_free(msg);
			return false;
		}

		return true;
	}

	bool isError(){
		if (m_error_code == SQLITE_OK){
			return false;
		}
		return true;
	}

	static int callback(void* data, int cols_count, char** cols_val, char** cols_key)
	{
		Result *res = (Result*)data;

		if (res->m_rows == 0){
			res->setColsKey(cols_count, cols_key);
		}
		res->addRow(cols_val);

		return 0;
	}

	int getLastErrorCode(){ return m_error_code; }
	char* getLastErrorMessage(){ return m_error_message; }



private:
	sqlite3 *m_db;
	int m_error_code;
	char *m_error_message = NULL;

	void saveMessage(const char* msg)
	{
		if (m_error_message != NULL){
			free(m_error_message);
		}

		m_error_message = (char*)malloc(strlen(msg) + 1);
		strcpy(m_error_message, msg);

	}
};